/*----------------------------------------------------------------------
 *
 * testbench description here
 *
 * NOTE : this is a fairly simple test bench and you should consider
 * setting up a test harness and using that instead.
 *
 *---------------------------------------------------------------------*/

`timescale 1ns/1ns

module test_lpcb ();

  parameter            TESTBENCH_TIMEOUTus = 80000;
  parameter            TEST_NAME = "test_lpcb";

  //----------------------------------------
  reg                 clk;
  wire                clk_en;
  wire                gated_clk;
  wire                gated_clk_en;

  reg                 reset;
  //----------------------------------------

  //----------------------------------------
  // serial port interface.
  reg                 txd_in;
  wire                rxd_out;

  // scaler value is supplied externally
  // values are clock rate / (8 x baud rate) - 1, so for:
  // 115200 @ 100MHz = 108
  //  57600 @ 100MHz = 216
  // 115200 @  90MHz =  97
  //  57600 @  90MHz = 194
  // 115200 @  50MHz =  53
  //  57600 @  50MHz = 108
  wire [7:0]          dcom_scaler;
  //----------------------------------------

  //----------------------------------------
  // lpcb interface
  wire                lpcb_frame_out;
  wire[3:0]           lpcb_cad_out;

  wire                lpcb_frame_in;
  wire [3:0]          lpcb_cad_in;
  //----------------------------------------

  //-----------------------------------------
  // stuff.
  wire [7:0] led_out;
  wire [3:0] c3_out;
  wire [3:0] c2_out;
  wire [3:0] c1_out;
  wire [3:0] c0_out;

  reg [3:0] button_in;
  reg [7:0] switch_in;
  reg c3_inc;
  reg c2_inc;
  reg c1_inc;
  reg c0_inc;
  //-----------------------------------------

  /*----------------------------------------------------------------*/

  /*AUTOREG*/

  /*AUTOWIRE*/
  // Beginning of automatic wires (for undeclared instantiated-module outputs)
  wire [3:0]            lpcb_cad_out_a;         // From hatch of lpcb_hatch.v
  wire                  lpcb_frame_out_a;       // From hatch of lpcb_hatch.v
  wire [3:0]            lpcb_tx_cad;            // From lpcb_tx of lpcb_tx.v
  wire                  lpcb_tx_frame;          // From lpcb_tx of lpcb_tx.v
  wire                  lpcb_tx_strobe;         // From lpcb_tx of lpcb_tx.v
  // End of automatics

  /*------------------------------------------------------------------
   *
   * local definitions and connections.
   *
   * */

`include "dcom_lpcb_tasks.vh"
`include "lpcb_hatch.vh"

  /*------------------------------------------------------------------
   *
   *
   *
   * */

  initial begin
    $display("module name = %s", TEST_NAME);
    $display("vzd file name = %s",{TEST_NAME,".netlist_vzd"});
  end

  initial begin
`ifdef VCD
 `ifdef NETLIST_SIM
  `ifdef VZD
    $dumpfile({TEST_NAME,".netlist_vzd"});
  `else
    $dumpfile({TEST_NAME,".netlist_vcd"});
  `endif
 `else
  `ifdef VZD
    $dumpfile({TEST_NAME,".vzd"});
  `else
    $dumpfile({TEST_NAME,".vcd"});
  `endif
 `endif
    $dumpvars(0);
`endif
  end


  integer              timeout;
  initial begin
    for (timeout=0 ; timeout < TESTBENCH_TIMEOUTus; timeout=timeout+1) #1000;
    $display("*** ERROR - tesbench timeout at %t.", $time);
    // $display("*** not a real test.");
    $finish();
  end

  /*------------------------------------------------------------------
   *
   *
   *
   * */

  //
  // system clocks.
  //
  initial clk = 0;
  always #10 clk <= ~clk;
  assign gated_clk = clk;
  assign gated_reset = reset;
  assign clk_en = 1'd1;
  assign gated_clk_en = 1'd1;

  // 115200 @  50MHz =  53
  assign                dcom_scaler = 8'd53;

  /*-----------------------------------------------------------------
   *
   *
   *
   * */

  integer               i,j,k;
  reg [31:0]            data, expected_data;
  reg [31:0]            data_a, data_b, data_c, data_d, data_e, data_f, data_g, data_h;
  reg [31:0]            expected_data_a, expected_data_b, expected_data_c, expected_data_d,
                        expected_data_e, expected_data_f, expected_data_g, expected_data_h;
  initial begin
    button_in  = 4'd0;
    switch_in  = $random;
    c3_inc     = 1'd0;
    c2_inc     = 1'd0;
    c1_inc     = 1'd0;
    c0_inc     = 1'd0;
    txd_in     = 1'd1;
    reset      = 1'd1;

    for (i=0 ; i<10; i=i+1) @ (posedge clk);

    reset = 1'd0;

    for (i=0 ; i<10; i=i+1) @ (posedge clk);

    uart_write(`big_reg, 32'h12345678);
    uart_read(`big_reg, data);
    $display("// got data 0x%x.", data);

    data_a = 32'h1;
    data_b = 32'h2;
    uart_write(`fifo_addr, 32'h0);
    for (i=0 ; i<16; i=i+1) begin
      uart_write_08_bytes(`fifo_data, data_a, data_b);
      data_a = data_a << 2;
      data_b = data_b << 2;
    end

    expected_data_a = 32'h1;
    expected_data_b = 32'h2;
    uart_write(`fifo_addr, 32'h0);
    for (i=0 ; i<16; i=i+1) begin
      uart_read_08_bytes(`fifo_data, data_a, data_b);
      if ((expected_data_a != data_a) || (expected_data_b != data_b)) begin
        $display("*** ERROR - expected data 0x%08x, 0x%08x, got 0x%08x, 0x%08x.",
                 expected_data_a, expected_data_b, data_a, data_b);
        $finish();
      end else begin
        $display("// got expected data 0x%08x, 0x%08x.", data_a, data_b);
      end
      expected_data_a = expected_data_a << 2;
      expected_data_b = expected_data_b << 2;
    end


    expected_data = 32'h2;
    for (i=0 ; i<8; i=i+1) begin
      uart_write(`big_reg, expected_data);
      uart_read(`big_reg, data);
      if (expected_data != data) begin
        $display("*** ERROR - expected data 0x%2x, got 0x%2x.", expected_data, data);
        $finish();
      end else begin
        $display("// got expected data 0x%2x.", data);
      end
      expected_data = expected_data << 4;
    end

    for (i=0 ; i<8 ; i=i+1) begin
      expected_data = $random;
      uart_write(`big_reg, expected_data);
      uart_read(`big_reg, data);
      if (expected_data != data) begin
        $display("*** ERROR - expected data 0x%2x, got 0x%2x.", expected_data, data);
        $finish();
      end else begin
        $display("// got expected data 0x%2x.", data);
      end
    end

    $display("*** TEST FINISHED.");
    $finish();
  end

  /*-----------------------------------------------------------------
   *
   *
   *
   * */

  wire [7:0]            fifo_addr_out;
  wire [31:0]           fifo_data_out;
  wire [31:0]           fifo_data_in;
  wire                  fifo_data_wen;

  reg [31:0]            fifo_data[0:255];
  always @ (posedge clk) if (fifo_data_wen) fifo_data[fifo_addr_out] <= fifo_data_out;
  assign                fifo_data_in = fifo_data[fifo_addr_out];

  /*-----------------------------------------------------------------
   *
   *
   *
   * */


  /* dcom_lpcb AUTO_TEMPLATE (
   ) */
  dcom_lpcb dcom
    (/*AUTOINST*/
     // Outputs
     .rxd_out                           (rxd_out),
     .lpcb_frame_out                    (lpcb_frame_out),
     .lpcb_cad_out                      (lpcb_cad_out[3:0]),
     // Inputs
     .clk                               (clk),
     .clk_en                            (clk_en),
     .reset                             (reset),
     .txd_in                            (txd_in),
     .dcom_scaler                       (dcom_scaler[7:0]),
     .lpcb_frame_in                     (lpcb_frame_in),
     .lpcb_cad_in                       (lpcb_cad_in[3:0]));


  /* lpcb_hatch AUTO_TEMPLATE (
   .\(lpcb_.*\)_out (\1_out_a[]),
   .\(lpcb_.*\)_in (\1_out[]),
   ) */
  lpcb_hatch hatch
    (/*AUTOINST*/
     // Outputs
     .lpcb_frame_out                    (lpcb_frame_out_a),      // Templated
     .lpcb_cad_out                      (lpcb_cad_out_a[3:0]),   // Templated
     .led_out                           (led_out[7:0]),
     .c3_out                            (c3_out[3:0]),
     .c2_out                            (c2_out[3:0]),
     .c1_out                            (c1_out[3:0]),
     .c0_out                            (c0_out[3:0]),
     .fifo_addr_out                     (fifo_addr_out[7:0]),
     .fifo_data_out                     (fifo_data_out[31:0]),
     .fifo_data_wen                     (fifo_data_wen),
     // Inputs
     .clk                               (clk),
     .clk_en                            (clk_en),
     .gated_clk                         (gated_clk),
     .gated_clk_en                      (gated_clk_en),
     .reset                             (reset),
     .lpcb_frame_in                     (lpcb_frame_out),        // Templated
     .lpcb_cad_in                       (lpcb_cad_out[3:0]),     // Templated
     .button_in                         (button_in[3:0]),
     .switch_in                         (switch_in[7:0]),
     .c3_inc                            (c3_inc),
     .c2_inc                            (c2_inc),
     .c1_inc                            (c1_inc),
     .c0_inc                            (c0_inc),
     .fifo_data_in                      (fifo_data_in[31:0]));

  /* lpcb_tx AUTO_TEMPLATE (
   .\(lpcb_.*\)_in (\1_out_a[]),
   ) */
  lpcb_tx lpcb_tx
    (/*AUTOINST*/
     // Outputs
     .lpcb_tx_strobe                    (lpcb_tx_strobe),
     .lpcb_tx_frame                     (lpcb_tx_frame),
     .lpcb_tx_cad                       (lpcb_tx_cad[3:0]),
     // Inputs
     .clk                               (clk),
     .reset                             (reset),
     .lpcb_frame_in                     (lpcb_frame_out_a),      // Templated
     .lpcb_cad_in                       (lpcb_cad_out_a[3:0]));   // Templated

  /* lpcb_rx AUTO_TEMPLATE (
   .lpcb_rx_\(.*\) (lpcb_tx_\1[]),
   .\(lpcb_.*\)_out (\1_in[]),
  ) */
  lpcb_rx lpcb_rx
    (/*AUTOINST*/
     // Outputs
     .lpcb_frame_out                    (lpcb_frame_in),         // Templated
     .lpcb_cad_out                      (lpcb_cad_in[3:0]),      // Templated
     // Inputs
     .clk                               (clk),
     .reset                             (reset),
     .lpcb_rx_strobe                    (lpcb_tx_strobe),        // Templated
     .lpcb_rx_frame                     (lpcb_tx_frame),         // Templated
     .lpcb_rx_cad                       (lpcb_tx_cad[3:0]));      // Templated

  /*----------------------------------------------------------------*/

endmodule // test_lpcb


// Local Variables:
// verilog-library-directories:(".")
// verilog-library-extensions:(".v")
// End:
